﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace VeinServerCsharp
{
    public partial class Main : Form
    {
        public Main()
        {
            InitializeComponent();
        }
        public bool RecordAllLog = false;

        //和客户端通信的套接字
        public Socket socketwatch = null;

        //客户端连接集合
        public static Dictionary<string, Socket> clientConnectionItems = new Dictionary<string, Socket> { };
        private void btsServerStart_Click(object sender, EventArgs e)
        {
            try
            {
                //var a = Program.XG_GetComApiVer("v1.4");
                string ip = "0.0.0.0";
                socketwatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socketwatch.NoDelay = false;
                socketwatch.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, true);
                socketwatch.ReceiveTimeout = 31 * 1000;
                IPAddress address = IPAddress.Parse(ip);
                IPEndPoint point = new IPEndPoint(address, 8080);
                socketwatch.Bind(point);
                socketwatch.Listen(20);
                Thread thread = new Thread(wacthconnecting);

                thread.IsBackground = true;
                thread.Start();
                appendText("开启监听");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
       public void wacthconnecting()
        {
            Socket conn = null;
            while (true)
            {
                try
                {
                    conn = socketwatch.Accept();
                }
                catch (Exception ex)
                {
                    appendText(ex.Message);
                    break;
                }
                try
                {
                    //获取客户端的ip和端口号
                    IPAddress clientIP = (conn.RemoteEndPoint as IPEndPoint).Address;
                    int clientPort = (conn.RemoteEndPoint as IPEndPoint).Port;

                    //客户端网络节点号
                    string remoteEndPointStr = conn.RemoteEndPoint.ToString();
                   
                    //添加客户端信息
                    clientConnectionItems.Add(remoteEndPointStr, conn);
                    appendText(string.Format("成功与{0}客户端建立连接", remoteEndPointStr));
                    appendText(string.Format("当前在线客户端统计：{0}", clientConnectionItems.Count));

                    AddOnlineItem(remoteEndPointStr);

                    IPEndPoint netPoint = conn.RemoteEndPoint as IPEndPoint;

                    //创建一个通信线程
                    ParameterizedThreadStart pts = new ParameterizedThreadStart(Recv);
                    Thread thread = new Thread(pts);
                    //设置为后台线程，UI主线程退出就都退出了
                    thread.IsBackground = true;
                    thread.Start(conn);
                }
                catch (Exception ex)
                {
                    appendText(ex.Message);
                    CSHelper.saveErrLog(ex.Message + "\n\r" + ex.StackTrace,"log");
                }
            }
        }

       public void Recv(object socketClientPara)
        {
            Socket socket = socketClientPara as Socket;
            string clientIp=socket.RemoteEndPoint.ToString();
            while (true)
            {
                //创建一个内存缓冲区，其大小为64*1024字节，同java
                byte[] recvBuf = new byte[64 * 1024];
                byte[] recvAll = new byte[0];
                //本次接收的字节数
                int RecvByteLen = 0;
                try
                {
                    if (socket != null)
                    {
                        RecvByteLen = socket.Receive(recvBuf);
                        if (RecvByteLen == 0)
                        {
                            continue;
                        }

                        //recvAll = recvBuf;
                        appendText(string.Format("RecvByte:{0} from{1}", RecvByteLen, clientIp));

                        if (recvBuf[0] == (byte)0xDD && recvBuf[1] == (byte)0xCC)
                        {
                            int address = recvBuf[2] & 0xff;
                            int cmd = recvBuf[3] & 0xff;

                            //860设备的长度和560采集到的图像大小不一样，所以socket发包的长度不一样
                            //860的datalen只占包的第四和第五位，校验和是占包的六七位
                            //560usb设备采集到的图像比较大，数组长度需要用正常的int大小来存byte为8位长度，int是32位长度
                            //实际上一个int需要4个byte才能存下来，560设备模拟客户端的时候datalen多增加了第六第七位，校验和占包的八九位
                            //860和560通过address来区分address=2代表560设备模拟socket的客户端,560比860设备的包头包尾多4个字节
                            int packHeadTailLen = 8;//860设备发包的包头包尾长度是8
                            bool is560Device = false;//如果是560 usb设备
                            if (address == 2)
                            {
                                is560Device = true;
                               
                            }
                            //datalen有效数据长度，除开包头包尾部分
                            int datalen = (recvBuf[4] & 0xff) + ((recvBuf[5] & 0xff) << 8);

                            if (is560Device)
                            {
                                packHeadTailLen += 4;//客户端增加了datalen的2位和校验和的2位byte，所以加4
                                datalen += ((recvBuf[6] & 0xff) << 16) + ((recvBuf[7] & 0xff) << 24);
                            }

                            appendText("接收到新包:address = " + address + ",cmd = " + cmd + ",datalen = " + datalen + ", from=" + clientIp);

                            byte[] b = new byte[RecvByteLen];
                            b = recvBuf.Skip(0).Take(RecvByteLen).ToArray();
                            recvAll = recvAll.Concat(b).ToArray();

                            if (RecvByteLen < (datalen + packHeadTailLen))
                            {
                                //剩余未接到的长度
                                int remain = (datalen + packHeadTailLen) - RecvByteLen;
                                while (true)
                                {
                                    try
                                    {
                                        var len = socket.Receive(recvBuf);
                                        byte[] c = new byte[len];
                                        c = recvBuf.Skip(0).Take(len).ToArray();

                                        RecvByteLen += len;
                                        recvAll = recvAll.Concat(c).ToArray();
                                    }
                                    catch (Exception ex)
                                    {
                                        appendText("剩余接收超时...");
                                        return;
                                    }
                                    remain = (datalen + packHeadTailLen) - RecvByteLen;
                                    appendText("RecvByte " + RecvByteLen + " remain " + remain + " from " + clientIp);

                                    if (RecvByteLen >= (datalen + packHeadTailLen))
                                    {
                                        appendText("接收完成 from" + clientIp);
                                        break;
                                    }
                                }
                            }
                            

                            //除掉包长度datalen之外占多少字节
                            int lenExceptDatalen = 6;
                            if (is560Device) lenExceptDatalen = 8;

                            //接收的包计算校验和
                            int checksum1 = MessageHandle.CheckSum(recvAll, datalen + lenExceptDatalen);

                            //计算客户端包发来的校验和
                            int checksum2 = (recvAll[datalen + 6] & 0xff) + ((recvAll[datalen + 7] & 0xff) << 8);
                            if (is560Device)
                            {   //兼容560设备发来的校验和
                                checksum2 = (recvAll[datalen + 8] & 0xff) + ((recvAll[datalen + 9] & 0xff) << 8);
                                checksum2 += (((recvAll[datalen + 10] & 0xff) << 16) + ((recvAll[datalen + 11] & 0xff) << 24));
                            }
                            if (checksum1 != checksum2)
                            {
                                appendText("校验和错误 CHECKSUM1 = " + checksum1 + "CHECKSUM2 = " + checksum2+" 差 = "+(checksum1-checksum2));
                            }
                            else
                            {
                                appendText("校验和正确 CHECKSUM1 = " + checksum1 + "CHECKSUM2 = " + checksum2);
                                MessageHandle mhObj = MessageHandle.getInstance(socket);
                                mhObj.RecMsgHandle(cmd, recvAll,datalen);

                            }
                            recvAll = null;
                        }
                        else
                        {
                            appendText("包头错误");
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                catch (Exception ex)
                {
                    //移出列表
                    clientConnectionItems.Remove(socket.RemoteEndPoint.ToString());
                    appendText("客户端" + socket.RemoteEndPoint + "已经中断连接" + "\r\n" + ex.Message + "\r\n" + ex.StackTrace + "\r\n");
                    appendText(string.Format("当前在线客户端统计：{0}",clientConnectionItems.Count));
                    RemoveOnlineItem(socket.RemoteEndPoint.ToString());
                    CSHelper.saveErrLog(ex.Message + "\n\r" + ex.StackTrace, "log");
                    //如果发生错误，忽略，重新搞个循环
                    socket.Close();
                    break;
                }
              
               
                finally
                {
                     Thread.Sleep(3000);
                }
            }
        }
       

        public string lastLogText = "";
        /// <summary>
        /// 添加到日志
        /// </summary>
        /// <param name="log">日志信息</param>
        private void appendText(string log, bool save = true)
        {
            Action<string> actionDelegate = (x) =>
            {
                if (this.richTextBox1.Text.Length > 20000)
                {
                    this.richTextBox1.Text = this.richTextBox1.Text.Substring(20000, this.richTextBox1.Text.Length - 20000);
                }
                this.richTextBox1.AppendText(DateTime.Now.ToString() + ":" + log);
                richTextBox1.AppendText(System.Environment.NewLine);
                this.richTextBox1.ScrollToCaret();
            };
            this.richTextBox1.Invoke(actionDelegate, log);
            if (RecordAllLog)
            {
                CSHelper.saveErrLog(log, "gateCtrlLog");
            }
        }

        /// <summary>
        /// 添加上线的指静脉设备
        /// </summary>
        /// <param name="itemName"></param>
        private void AddOnlineItem(string itemName)
        {
            Action<string> actionDelegate = (x) =>
                {
                    this.clbOnlineDevices.Items.Add(itemName);
                };
            this.clbOnlineDevices.Invoke(actionDelegate, itemName);
        }

        /// <summary>
        /// 移出下线的指静脉设备
        /// </summary>
        /// <param name="itemName"></param>
        private void RemoveOnlineItem(string itemName)
        {
            Action<string> actionDelegate = (x) =>
            {
                this.clbOnlineDevices.Items.Remove(itemName);
            };
            this.clbOnlineDevices.Invoke(actionDelegate, itemName);
        }

        #region 接受到windows消息|处理指静脉设备发来的窗体消息
        //int a = 0, b = 0;
        //protected override void DefWndProc(ref System.Windows.Forms.Message m)
        //{
            //try
            //{

            //    a++;
            //    //richTextBox1.AppendText("a:" + a + " b:" + b + "Msg:" + m.Msg + " Result:" + m.Result + " WParam:" + m.WParam + " LParam:" + m.LParam + "\n\r");
            //    switch (m.Msg)
            //    {
            //        case LL_MSG:
            //            b++;
            //            //richTextBox1.AppendText(m.Msg + " " + m.Result + " " + m.WParam + "" + m.LParam);
            //            if (m.LParam == (IntPtr)FD_CLOSE)
            //            {
            //                int i = 0;
            //                while (i < checkedListBox1.Items.Count)
            //                {
            //                    if (m.WParam == GetSock(i))
            //                    {
            //                        checkedListBox1.Items.RemoveAt(i);
            //                        continue;
            //                    }
            //                    i++;
            //                }

            //                    }
            //                    else if (cmd == CMD_ENTRECO)
            //                    {
            //                        int opret;
            //                        if (LL_GetData(m.WParam, cmd, ref tag, ref devid, ref dalen, out opret) == 0)
            //                        {
            //                            richTextBox1.AppendText(string.Format("{0,-20}{1,-16} {2}(确认记录数)", "LL_EnterReco", GetIP(i), opret));
            //                            richTextBox1.AppendText(System.Environment.NewLine);
            //                            richTextBox1.ScrollToCaret();
            //                        }
            //                    }
            //                    else if (cmd == CMD_GETRECO)
            //                    {
            //                        //ll_iorec[] iorec = new ll_iorec[UPMAXRECO];
            //                        //IntPtr dptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ll_iorec)) * UPMAXRECO);
            //                        //if (LL_GetData(m.WParam, cmd, ref tag, ref devid, ref dalen, dptr) == 0)
            //                        //{
            //                        //    int rcou = (int)(dalen / Marshal.SizeOf(typeof(ll_iorec)));
            //                        //    for (int ri = 0; ri < rcou; ri++)
            //                        //        iorec[ri] = (ll_iorec)Marshal.PtrToStructure(dptr + Marshal.SizeOf(typeof(ll_iorec)) * ri, typeof(ll_iorec));
            //                        //    richTextBox1.AppendText(string.Format("{0,-20}{1,-16} {2}(取记录)", "LL_GetReco", GetIP(i), rcou));
            //                        //    richTextBox1.AppendText(System.Environment.NewLine);
            //                        //    for (int ri = 0; ri < rcou; ri++)
            //                        //    {
            //                        //        richTextBox1.AppendText(string.Format("读头：{0,-20}", iorec[ri].rd));
            //                        //        richTextBox1.AppendText(System.Environment.NewLine);
            //                        //        richTextBox1.AppendText(string.Format("人员ID：{0,-20}", iorec[ri].pid));
            //                        //        richTextBox1.AppendText(System.Environment.NewLine);
            //                        //        richTextBox1.AppendText(string.Format("卡号：{0,-20}", iorec[ri].cr));
            //                        //        richTextBox1.AppendText(System.Environment.NewLine);
            //                        //        richTextBox1.AppendText(string.Format("编码：{0,-20}", ASCIIEncoding.GetEncoding("gb2312").GetString(iorec[ri].sn)));
            //                        //        richTextBox1.AppendText(System.Environment.NewLine);
            //                        //        richTextBox1.AppendText(string.Format("消费：{0,-20}", iorec[ri].xf));
            //                        //        richTextBox1.AppendText(System.Environment.NewLine);
            //                        //        richTextBox1.AppendText(string.Format("余额：{0,-20}", iorec[ri].ye));
            //                        //        richTextBox1.AppendText(System.Environment.NewLine);
            //                        //        richTextBox1.AppendText(string.Format("时间：{0}-{1}-{2} {3}:{4}:{5}", iorec[ri].year, iorec[ri].month, iorec[ri].day, iorec[ri].hour, iorec[ri].minute, iorec[ri].sec));
            //                        //        richTextBox1.AppendText(System.Environment.NewLine);
            //                        //        richTextBox1.AppendText(string.Format("状态：{0,-20}", Get_IoSt(iorec[ri].iost)));
            //                        //        richTextBox1.AppendText(System.Environment.NewLine);
            //                        //    }
            //                        //    richTextBox1.ScrollToCaret();
            //                        //}
            //                        //Marshal.FreeHGlobal(dptr);
            //                    }
            //                    else if (cmd == CMD_SETRECOPOS)
            //                    {
            //                        int recopos;
            //                        if (LL_GetData(m.WParam, cmd, ref tag, ref devid, ref dalen, out recopos) == 0)
            //                        {
            //                            if (recopos >= 0)
            //                                richTextBox1.AppendText(string.Format("置读记录指针成功！指向：{0}", recopos));
            //                            else
            //                                richTextBox1.AppendText("置读记录指针失败！");
            //                            richTextBox1.AppendText(System.Environment.NewLine);
            //                            richTextBox1.ScrollToCaret();
            //                        }
            //                    }
            //                    else if (cmd == CMD_GETRECOPOS)
            //                    {
            //                        int recopos;
            //                        if (LL_GetData(m.WParam, cmd, ref tag, ref devid, ref dalen, out recopos) == 0)
            //                        {
            //                            richTextBox1.AppendText(string.Format("取读记录指针：{0}", recopos));
            //                            richTextBox1.AppendText(System.Environment.NewLine);
            //                            richTextBox1.ScrollToCaret();
            //                        }
            //                    }
            //                    else if (cmd == CMD_DELPER)
            //                    {
            //                        int delret;
            //                        if (LL_GetData(m.WParam, cmd, ref tag, ref devid, ref dalen, out delret) == 0)
            //                        {
            //                            richTextBox1.AppendText(string.Format("清空人员（0=成功)：{0}", delret));
            //                            richTextBox1.AppendText(System.Environment.NewLine);
            //                            richTextBox1.ScrollToCaret();
            //                        }
            //                    }
            //                    else if (cmd == CMD_GETPERCOU)
            //                    {
            //                        int percou;
            //                        if (LL_GetData(m.WParam, cmd, ref tag, ref devid, ref dalen, out percou) == 0)
            //                        {
            //                            richTextBox1.AppendText(string.Format("人员数：{0}", percou));
            //                            richTextBox1.AppendText(System.Environment.NewLine);
            //                            richTextBox1.ScrollToCaret();
            //                        }
            //                    }
            //                    else if (cmd == CMD_GETMAXPER)
            //                    {
            //                        int maxper;
            //                        if (LL_GetData(m.WParam, cmd, ref tag, ref devid, ref dalen, out maxper) == 0)
            //                        {
            //                            richTextBox1.AppendText(string.Format("人员容量：{0}", maxper));
            //                            richTextBox1.AppendText(System.Environment.NewLine);
            //                            richTextBox1.ScrollToCaret();
            //                        }
            //                    }
            //                    else if (cmd == CMD_EDITPER)
            //                    {
            //                        //ll_peropt[] peropt = new ll_peropt[UPMAXRECO];
            //                        //IntPtr dptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ll_peropt)) * UPMAXRECO);
            //                        //if (LL_GetData(m.WParam, cmd, ref tag, ref devid, ref dalen, dptr) == 0)
            //                        //{
            //                        //    int rcou = (int)(dalen / Marshal.SizeOf(typeof(ll_peropt)));
            //                        //    for (int ri = 0; ri < rcou; ri++)
            //                        //        peropt[ri] = (ll_peropt)Marshal.PtrToStructure(dptr + Marshal.SizeOf(typeof(ll_peropt)) * ri, typeof(ll_peropt));
            //                        //    richTextBox1.AppendText(string.Format("{0,-20}{1,-16} {2}(编辑人员)", "LL_EditPer", GetIP(i), rcou));
            //                        //    richTextBox1.AppendText(System.Environment.NewLine);
            //                        //    for (int ri = 0; ri < rcou; ri++)
            //                        //    {
            //                        //        richTextBox1.AppendText(string.Format("人员ID：{0,-20}", peropt[ri].pid));
            //                        //        richTextBox1.AppendText(System.Environment.NewLine);
            //                        //        richTextBox1.AppendText(string.Format("状态：{0,-20}，(0=成功）", peropt[ri].optret));
            //                        //        richTextBox1.AppendText(System.Environment.NewLine);
            //                        //    }
            //                        //    richTextBox1.ScrollToCaret();
            //                        //}
            //                        //Marshal.FreeHGlobal(dptr);
            //                    }
            //                    else if (cmd == CMD_FINGERDATA)
            //                    {
            //                        byte[] fda = new byte[520];//改+1
            //                        if (LL_GetData(m.WParam, cmd, ref tag, ref devid, ref dalen, ref fda[0]) == 0)
            //                        {
            //                            string fstr = "";
            //                            for (int x = 0; x < dalen; x++)
            //                                fstr = fstr + fda[x].ToString("x");
            //                            richTextBox1.AppendText(string.Format("{0,-20}{1,-16} :{2}", "指纹数据", GetIP(i), fstr));
            //                            richTextBox1.AppendText(System.Environment.NewLine);
            //                            richTextBox1.ScrollToCaret();
            //                        }
            //                    }
            //                    else
            //                        LL_GetData(m.WParam, cmd, ref tag, ref devid, ref dalen, (IntPtr)null);
            //                }
            //            }
            //            break;
            //        default:
            //            base.DefWndProc(ref m);
            //            break;
            //    }
            //}
            //catch (Exception ex)
            //{
            //    CSHelper.saveErrLog("句柄接受消息报错" + ex.Message + "\n\r" + ex.StackTrace, "gateCtrlLog");
            //}
        //}

        #endregion
    }
}
